package com.atguigu.srb.core.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.atguigu.srb.common.exception.Assert;
import com.atguigu.srb.common.result.ResponseEnum;
import com.atguigu.srb.core.listener.ExcelDictDTOListener;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.atguigu.srb.core.mapper.DictMapper;
import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import com.atguigu.srb.core.service.DictService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据字典 服务实现类
 * </p>
 *
 * @author lsyandwh
 * @since 2022-12-02
 */
@Transactional
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String CACHE_KEY = "admin.core.dict.";

    @Override
    public void insertBatch(InputStream inputStream) {
        EasyExcel
                .read(inputStream, ExcelDictDTO.class, new ExcelDictDTOListener(baseMapper))
                .sheet()
                .doRead();
    }

    @Override
    public List<ExcelDictDTO> exportDict() {

        List<ExcelDictDTO> list = null;

        //获取字典表所以数据
        List<Dict> dicts = baseMapper.selectList(null);

        //将数据转换成ExcelDictDTO
        list = dicts.stream()
                .map(dict -> {
                    ExcelDictDTO excelDictDTO = new ExcelDictDTO();
                    //将原数据拷贝到新集合中
                    BeanUtils.copyProperties(dict,excelDictDTO);
                    return excelDictDTO;
                }).collect(Collectors.toList());
        return list;
    }

    @Override
    public List<Dict> getByParentId(Long parentId) {

        //先查询redis
        String result = (String) redisTemplate.opsForValue().get(CACHE_KEY+ parentId);
        List<Dict> dictList = null;

        if(StringUtils.isEmpty(result)){
            //redis中不存在此数据，查询数据库
            dictList = getListByParentId(parentId);

            //如果使用parentId查询数据库为空则说明当前parentId不存在
            if(CollectionUtils.isEmpty(dictList)){
                //设置一个空值，并设置过期时间
                redisTemplate.opsForValue().set(CACHE_KEY + parentId,new ArrayList<Dict>(),5, TimeUnit.MINUTES);
            }else {
                //将数据存储到redis中
                String str = JSON.toJSONString(dictList);
                redisTemplate.opsForValue().set(CACHE_KEY + parentId,str);
            }
        }else {
            dictList = JSON.parseObject(result, List.class);
        }
        return dictList;
    }

    @Override
    public List<Dict> getDictListByCode(String dictCode) {

        //1.根据dictCode查询父节点数据
        QueryWrapper<Dict> wrapper = new QueryWrapper<Dict>()
                .eq("dict_code",dictCode);

        Dict dict = baseMapper.selectOne(wrapper);
        Assert.notNull(dict, ResponseEnum.ERROR);

        //2.根据父节点id查询子节点
        wrapper.clear();//清除wrapper中数据
        wrapper.eq("parent_id",dict.getId());

        List<Dict> list = baseMapper.selectList(wrapper);

        return list;
    }

    /**
     * 从数据库中根据ParentId查询
     * @param parentId
     * @return
     */
    private List<Dict> getListByParentId(Long parentId){
        //构建查询条件
        QueryWrapper<Dict> wrapper = new QueryWrapper<Dict>()
                .eq("parent_id",parentId);

        //根据parentId查询子节点
        List<Dict> list = baseMapper.selectList(wrapper);

        List<Dict> collect = list.stream().map(dict -> {

            //设置当前节点是否有子节点
            dict.setHasChildren((getListByParentId(dict.getId()).size()) > 0);

            return dict;
        }).collect(Collectors.toList());

        return collect;
    }
}
